using UnityEngine;

//负责整个游戏
public class Game : MonoBehaviour
{
    //地图尺寸
    [SerializeField]
    Vector2Int boardSize = new Vector2Int(11, 11);

    [SerializeField]
    GameBroad board = default;

    //工厂引用
    [SerializeField]
    GameTileContentFactory tileContentFactory = default;
    
    [SerializeField]
    WarFactory warFactory = default;


    // 敌人集合
    GameBehaviorCollection enemies = new GameBehaviorCollection();
    //非敌人
    GameBehaviorCollection nonEnemies = new GameBehaviorCollection();

    TowerType selectedTowerType;

    static Game instance;

    //过多敌人到达目的地则输掉游戏
    [SerializeField, Range(0,100)]
    int startingPlayerHealth = 10;

    int playerHealth;

    //游戏流逝速度，用于暂停游戏
    const float pausedTimeScale = 0f;

    //游戏播放速度
    [SerializeField,Range(1f, 10f)]
    float playerSpeed = 1f;

    //情境引用
    [SerializeField]
    GameScenario scenario = default;
    GameScenario.State activeScenario;


    private void Awake() {
        playerHealth = startingPlayerHealth;
        board.Initialize(boardSize, tileContentFactory);
        board.ShowGrid = true;
        activeScenario = scenario.Begin();
    }

    //Unity编辑器可能会在组件更改后在在组件上调用它
    //包括何时将它们添加到游戏对象中，加载场景之后，重新编译之后，通过检查器进行编译之后，撤销/重做之后以及组件重置之后等。
    //只能在 Editor 中调用
    //OnValidate是我们代码中唯一应向组件配置字段分配值的地方
    private void OnValidate() {
        if(boardSize.x < 2){
            boardSize.x = 2;
        }
        if(boardSize.y < 2){
            boardSize.y = 2;
        }
    }

    //播放器的输入
    //将Input.mousePosition作为其参数在主摄像机上调用ScreenPointToRay,可以将单击转换为射线。    
    Ray TouchRay => Camera.main.ScreenPointToRay(Input.mousePosition);
    
    private void Update() {
        if(Input.GetMouseButtonDown(0))//检测是否按下主鼠标按钮
        {
            HandleTouch();//添加墙体
        }else if(Input.GetMouseButton(1))
        {
            HandleAlertNativeTouch();//添加目的地
        }

        if(Input.GetKeyDown(KeyCode.V))
        {
            board.ShowPaths = !board.ShowPaths;//切换显示路径
        }
        if(Input.GetKeyDown(KeyCode.G))
        {
            board.ShowGrid = !board.ShowGrid;//切换显示网格
        }

        if(Input.GetKeyDown(KeyCode.Alpha1))
        {//按键1是激光塔
            selectedTowerType = TowerType.laser;
        }else if(Input.GetKeyDown(KeyCode.Alpha2))
        {//按键2是迫击炮
            selectedTowerType = TowerType.Mortar;
        }

        if(Input.GetKeyDown(KeyCode.Space))
        {//空格暂停
            //Time.timeScale时间流逝的标度，可以用于慢动作
            Time.timeScale = Time.timeScale > pausedTimeScale ? pausedTimeScale : playerSpeed;
        }else if(Time.timeScale > pausedTimeScale)
        {//调整游戏速度
            Time.timeScale = playerSpeed;
        }

        if(Input.GetKeyDown(KeyCode.B))
        {//开始新游戏
            BeginNewGame();
        }
        

        if(playerHealth <= 0 && startingPlayerHealth > 0)
        {//生命值归0 游戏失败
            Debug.Log("Defeat!");
            BeginNewGame();
        }

        if(!activeScenario.Progress() && enemies.IsEmpty)
        {//敌人走完，还没失败则成功
            Debug.Log("Victory!");
            BeginNewGame();
            activeScenario.Progress();
        }

        //怪物列表刷新
        enemies.GameUpdate();

        //在对象的变换更改时立即强制立即同步
        Physics.SyncTransforms();
        //棋盘更新
        board.GameUpdate();

        nonEnemies.GameUpdate();
    }

    //生成怪物
    public static void SpawnEnemy(EnemyFactory factory, EnemyType type)
    {
        GameTile spawnPoint = instance.board.GetSpawnPoint(
            Random.Range(0, instance.board.SpawnPointCount));
        Enemy enemy = factory.Get(type);
        enemy.SpawnOn(spawnPoint);
        instance.enemies.Add(enemy);
    }

    void HandleAlertNativeTouch(){
        GameTile tile = board.GetTile(TouchRay);
        if(tile != null){
            if(Input.GetKey(KeyCode.LeftShift)){
                board.ToggleDestination(tile);//按住shift的时候 点击右键切换为目的地
            }else{
                board.ToggleSpawnPoint(tile);//点击鼠标右键将切换为出生点
            }
            
        }
    }

    void HandleTouch(){
        GameTile tile = board.GetTile(TouchRay);
        if(tile != null){
            if(Input.GetKey(KeyCode.LeftShift))
            {
                board.ToggleTower(tile, selectedTowerType);
            }else
                board.ToggleWall(tile);
        }
    }

    //生成shell
    public static Shell SpawnShell()
    {
        Shell shell = instance.warFactory.shell;
        instance.nonEnemies.Add(shell);
        return shell;
    }

    void OnEnable()
    {
        instance = this;
    }

    public static Explosion SpawnExplosion()
    {
        Explosion explosion = instance.warFactory.Explosion;
        instance.nonEnemies.Add(explosion);
        return explosion;
    }

    void BeginNewGame()
    {//清除敌人、非敌人和游戏地图，然后开始一个新的情景
        playerHealth = startingPlayerHealth;
        enemies.Clear();
        nonEnemies.Clear();
        board.Clear();
        activeScenario = scenario.Begin();
    }

    public static  void EnemyReachedDestination()
    {//如有怪物到终点则伤害减1
        instance.playerHealth -= 1;
    }

}